/*
 * @version: 1.0
 * @Author: zhl
 * @Date: 2021-08-25 15:36:01
 * @LastEditors: zhl
 * @LastEditTime: 2021-09-23 19:09:46
 * @Description: file content
 */
#include "common.h"

#include <stdio.h>
#ifdef _WIN32
#include <io.h>
#elif __linux__
    #include "findfirst.h"
#endif
#include <fcntl.h>

#include <sys/stat.h>
#include <sys/types.h>
#include <sys/timeb.h>
#include <sys/time.h>
#include <sys/select.h>
#include <dirent.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>

// #define _XOPEN_SOURCE
// #define _GNU_SOURCE
// #define __USE_XOPEN
#include <time.h>
#include <errno.h>

// #include <fcntl.h>
// #include <sys/stat.h>
// #include <sys/types.h>
// #include <sys/time.h>
// #define _XOPEN_SOURCE
// #define __USE_XOPEN
// #include <time.h>
// #include <pthread.h>




#define BUF_SIZE 1024

char *get_extension(char *filename){
    if((NULL == filename) || (1 > strlen(filename))){
        return NULL;
    }
    char *ext=strrchr(filename,'.');
	if (ext)
	{    
		*ext='\0';    
		ext++;
	}
    return ext;
}

void millisecond_sleep(int ms){
/* 毫秒级 延时 */
    struct timeval delay;
    delay.tv_sec = ms / 1000;
    delay.tv_usec = (ms % 1000) * 1000; // ms
    select(0, NULL, NULL, NULL, &delay);
}
//此方法有待验证
char* get_uart_timestamp(char* timestamp){
    struct timeb tv;
    struct tm *t;
    char str_t[64] = {0};
    if(NULL == timestamp){
        return NULL;
    }
    ftime(&tv);
    t = localtime(&tv.time);    

    snprintf(str_t, sizeof(str_t), "%d-%02d-%02dT%02d:%02d:%02d.%03u+0800", 1900+t->tm_year, 1+t->tm_mon, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec, tv.millitm);
    timestamp = str_t;
    strcpy(timestamp, str_t);
    return timestamp;
}
//根据时间字串获取时间戳
uint64_t get_timestamp_by_time_string(char* str_time){
    if(NULL == str_time){
        return get_timestamp();
    }
    struct tm t;
    strptime(str_time, "%H:%M:%s", &t);
    return (today_timestamp() + (t.tm_hour*60+t.tm_min)*60);
}
//根据日期时间字符串2019-03-01T09:30:08.230+0800  获取时间
uint64_t get_timestamp_by_uartstr(char* date_time)
{
    if (NULL == date_time){
        return get_timestamp();
    }
    struct tm tm1;
    uint32_t  t_us;
        
    sscanf(date_time, "%d-%d-%dT%d:%d:%d.%u+", &tm1.tm_year, &tm1.tm_mon, &tm1.tm_mday, &tm1.tm_hour, &tm1.tm_min, &tm1.tm_sec,&t_us);
    strptime(date_time, "%Y-%m-%dT%H:%M%s.", &tm1);
     
    time_t tt;
    tt = mktime(&tm1);
    
    uint64_t ms = (uint64_t)tt * 1000 + t_us / 1000;

    return ms;
}

//获取当前时间戳,毫秒级
uint64_t get_timestamp(){
    struct timeval tp;
    gettimeofday(&tp, NULL);
    uint64_t ms = (uint64_t)tp.tv_sec * 1000 + (uint64_t)tp.tv_usec / 1000;
    return ms;
}
//计算指定时间戳(秒级)，0点的时间戳
uint64_t timestamp_zero_time(uint64_t ts){
    time_t t = (time_t)ts;
    struct tm * tm= localtime(&t);
    tm->tm_hour = 0;
    tm->tm_min = 0;
    tm->tm_sec = 0;
    return  mktime(tm);
}
//根据毫秒数获取字符串时间戳, 线程不可重入
char* get_uart_timestamp_withms(uint64_t tms)
{
    static char timestamp[64];
    memset(timestamp, 0, sizeof(timestamp));
    time_t ts = (time_t)(tms / 1000);
    uint16_t ms = (uint16_t)(tms % 1000);
    struct tm * t = localtime(&ts);

    snprintf(timestamp, sizeof(timestamp), "%d-%02d-%02dT%02d:%02d:%02d.%03u+0800", 1900 + t->tm_year, 1 + t->tm_mon, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec, ms);

    return timestamp;
}
//当前日期0点的时间戳，秒级
uint64_t today_timestamp()
{   
    time_t t = time(NULL);
    return timestamp_zero_time(t);
}
uint64_t today_level_time_s(){
    time_t t = time(NULL);
    return (timestamp_zero_time(t)+86400-t);
}
//
int exec_cmd(char *cmd, char *result, int len){

    if((NULL == cmd) || (NULL == result) || (1 > len)){
        return -1;
    }

    FILE *fp = NULL; 
    fp=popen(cmd, "r"); 
    if(NULL == fp){
        return -1;
    }
    if(NULL == fgets(result, len,fp)){
        pclose(fp);
        return -1;
    } 
    pclose(fp);

    return 0;
}
/*
 函数说明：对字符串中所有指定的子串进行替换
 参数：
string resource_str           //源字符串
string sub_str                //被替换字符串
string new_str                //替换字符串
返回值: string
 */
// std::string string_replace(const std::string &resource_str, const std::string &sub_str, std::string new_str){
//     std::string dst_str = resource_str;
//     std::string::size_type pos = 0;
//     while((pos = dst_str.find(sub_str)) != std::string::npos)   //替换所有指定字串
//     {
//         dst_str.replace(pos, sub_str.length(), new_str);
//     }
//     return dst_str;
// }

void bswap_16(uint8_t *data){
    data[0] = data[0] ^ data[1];
    data[1] = data[0] ^ data[1];
    data[0] = data[0] ^ data[1];
}

void wswap_32(uint16_t *data){
    data[0] = data[0] ^ data[1];
    data[1] = data[0] ^ data[1];
    data[0] = data[0] ^ data[1];
}
//
// int get_dev_sn(char *sn, int sn_len){
//     if((NULL == sn) || (1 > sn_len)){
//         return -1;
//     }
//     get_sn(sn, sn_len);
//     if(0 < sn_len){
//         return sn_len;
//     }else{
//         return getDevSN(sn, sn_len);
//     }
// }

// int float_compare(std::string f1, std::string f2){

//     size_t pos1 = f1.find(".", 0);
//     size_t pos2 = f2.find(".", 0);

//     long long l1 = std::stoll(f1.substr(0, pos1));
//     long long l2 = std::stoll(f2.substr(0, pos2)); 
//     if(l1 > l2){
//         return 1;
//     } else if(l1 < l2){
//         return -1;
//     }

//     // std::string str_decimal1 = f1.substr(pos1+1, f1.size());
//     // std::string str_decimal2 = f2.substr(pos2+1, f2.size());
//     int ret = f1.substr(pos1+1, f1.size()).compare(f2.substr(pos2+1, f2.size()));
//     if(0 < ret){
//         return 1;
//     } else if (0 > ret){
//         return -1;
//     }

//     return 0;
// }
//
void print_buf(char *buf, int buf_len){
    if((NULL == buf) || (1 > buf_len)){
        return ;
    }
    printf("================================================\n");
    printf("长度: %d\n", buf_len);
    for(int i = 0; i < buf_len; i++){
        printf(" %02X", buf[i]);
        if(i%16 == 15){
            printf("\n");
        }
    }
    printf("\n");
    printf("================================================\n");
}
//
int exec_self(char **argv){
    // std::this_thread::sleep_for(std::chrono::milliseconds(2000));
    sleep(2);
    return execv("/proc/self/exe", argv);
}

pid_t get_processpid_byname(const char *task_name, pid_t cur_pid)
{
    pid_t pid =-1;

    DIR *dir;
    struct dirent *ptr;
    FILE *fp;
    char filepath[256];
    char cur_task_name[256];
    char buf[BUF_SIZE];

    dir = opendir("/proc");
    if (NULL != dir)
    {
        while ((ptr = readdir(dir)) != NULL) //循环读取/proc下的每一个文件/文件夹
        {
            if ((strcmp(ptr->d_name, ".") == 0) || (strcmp(ptr->d_name, "..") == 0))
                continue;
            if (DT_DIR != ptr->d_type)
                continue;

            sprintf(filepath, "/proc/%s/status", ptr->d_name);
            fp = fopen(filepath, "r");
            if (NULL != fp)
            {
                if (fgets(buf, BUF_SIZE - 1, fp) == NULL){
                    fclose(fp);
                    continue;
                }

                sscanf(buf, "%*s %s", cur_task_name);  
                //如果文件内容满足要求则打印路径的名字（即进程的PID）
                if (!strcmp(cur_task_name, task_name))
                {
                    pid = atoi(ptr->d_name);
                    printf("find proc %s pid is%d \n", task_name, pid);
                    if (pid != cur_pid){
                        fclose(fp);
                        break;
                    }
                }
                fclose(fp);
            }
        }
        closedir(dir);
    }

    return pid;
}
//如果是在一个程序的循环中不断调用这个函数，那么是没有效果的
//虽然也是使用的系统的时间函数来初始化随机数发生器，但程序的
//执行速度太快了，可能执行1000次循环返回的秒数都是一样的
//time返回时间戳
void get_rand_str(char *s,int num){
    if(NULL == s){
        return ;
    }
    //定义随机生成字符串表
    const char *str = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
    int i,lstr;
    char ss[2] = {0};
    lstr = strlen(str);//计算字符串长度
    srand((unsigned int)time((time_t *)NULL));//使用系统时间来初始化随机数发生器
    for(i = 1; i <= num; i++){//按指定大小返回相应的字符串
        sprintf(ss,"%c",str[(rand()%lstr)]);//rand()%lstr 可随机返回0-71之间的整数, str[0-71]可随机得到其中的字符
        strcat(s,ss);//将随机生成的字符串连接到指定数组后面
    }
}